﻿using Dora.Orm.SqlSugarCore.UnitOfWork;
using Dora.Services.AdminUser.Dto.QueryDto;
using Dora.Services.AdminUser.Dto.SaveDto;
using Dora.Services.AdminUser.Dto.ViewDto;
using Dora.Services.AdminUser.Entities;
using Dora.Services.AdminUser.IApplication;
using Dora.Services.AdminUser.Repository.Repositorys;
using Dora.Tools.Enums.AdminUser;
using Dora.Tools.Utility;
using Dora.Tools.Utility.Const;
using Dora.Tools.Utility.Models;
using Dora.Tools.Utility.Redis;
using Microsoft.Extensions.Logging;
using Surging.Core.Common;
using Surging.Core.CPlatform.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dora.Services.AdminUser.Application.Base;
using Dora.Tools.Enums;

namespace Dora.Services.AdminUser.Application
{
    /// <summary>
    /// 美程用户表服务
    /// </summary>
    [ModuleName(DoraModuleName.AdminUser)]
    public class DoraUserService : DoraServiceBase, IDoraUserService
    {
        private ISugarUnitOfWork _unitOfWork;
        private readonly DoraUserRepository _repository;
        private readonly DoraUserRoleMapRepository _doraUserRoleMapRepository;
        private readonly PermissionRepository _permissionRepository;
        //private readonly UserLoginLogRepository _doraUserLoginLogRepository;
        public DoraUserService(ISugarUnitOfWork unitOfWork
            ) : base(unitOfWork)
        {
            _unitOfWork = unitOfWork;
            _repository = new DoraUserRepository(unitOfWork);
            _doraUserRoleMapRepository = new DoraUserRoleMapRepository(unitOfWork);
            _permissionRepository = new PermissionRepository(unitOfWork);
            //_doraUserLoginLogRepository = new UserLoginLogRepository(unitOfWork);
        }


        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<ResultDto<DoraUserEntity>> Create(DoraUserEntity entity)
        {
            entity.CreatedTime = DateTime.Now;
            entity.UpdatedTime = DateTime.Now;
            entity.PasswordSalt = Guid.NewGuid().ToString();

            if (!VerifyHelper.IsMobilePhone(entity.Mobile))
            {
                return ResultDto<DoraUserEntity>.Error("请输入正确的手机号");
            }

            if (string.IsNullOrWhiteSpace(entity.RealName))
            {
                return ResultDto<DoraUserEntity>.Error("请输入真实姓名");
            }

            if (!string.IsNullOrEmpty(entity.UserName))
            {
                var existUserName= await _repository.ExistUserName(entity.UserName, entity.Id);
                if (existUserName)
                {
                    return ResultDto<DoraUserEntity>.Error("用户名已经存在");
                }
            }

            var existMobile = await _repository.ExistVerifiedMobile(entity.Mobile, entity.Id);
            if (existMobile)
            {
                return ResultDto<DoraUserEntity>.Error("手机号已经存在");
            }

            entity.MobileIsVerified = 1;

            if (string.IsNullOrEmpty(entity.Password))
            {
                entity.Password = DEncryptHelper.GetInitPassword(entity.Mobile, entity.PasswordSalt);
            }
            else
            {
                entity.Password = DEncryptHelper.GetInitPassword(entity.Password, entity.PasswordSalt);
            }

            var result = await _repository.InsertAsync(entity);
            result.Password = "";//不给前台返回
            result.PasswordSalt = "";//不给前台返回
            return ResultDto<DoraUserEntity>.Success(result);
        }


        /// <summary>
        /// 根据Id获取一个实体对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DoraUserEntity> GetById(Guid id)
        {
            return await _repository.FirstOrDefaultAsync(id);
        }


        /// <summary>
        /// 分页获取数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageDataList<DoraUserListDto>> GetPageList(DoraUserQueryDto input)
        {
            #region 部门Id转换成用户Id
            if (input.DepartmentIdList?.Count > 0)
            {
                //var userIdList = await _edmRepository.GetEmployeeIdListByDeptIdList(input.DepartmentIdList);
                //if (input.UserIdList == null)
                //{
                //    input.UserIdList = new List<Guid>();
                //}

                //if (userIdList?.Count > 0)
                //{
                //    input.UserIdList.AddRange(userIdList);
                //}
                //else
                //{
                //    input.UserIdList.Add(Guid.Empty);
                //}
            }
            #endregion
            var result = await _repository.GetPageList(input);
            if (result?.PageData?.Count() > 0)
            {
                var userIdList = result.PageData.Select(p => p.Id).ToList();
                #region 加载部门与角色
                //var deptAllList = await _edmRepository.GetListByEmployeeIdList(employeeIdList);
                var roleAllList = await _doraUserRoleMapRepository.GetListByUserIdList(userIdList);
                foreach (var item in result.PageData)
                {
                    //if (deptAllList?.Count > 0)
                    //{
                    //    item.DepartmentNames = "";
                    //    var list = deptAllList.Where(it => it.EmployeeId == item.Id);
                    //    if (list?.Count() > 0)
                    //    {
                    //        item.DepartmentNames = string.Join(ConstValue.ChineseSeparatorChar, list.Select(it => it.DepartmentName).ToArray());
                    //    }
                    //}

                    if (roleAllList?.Count > 0)
                    {
                        item.RoleName = "";
                        var list = roleAllList.Where(it => it.UserId == item.Id);
                        if (list?.Count() > 0)
                        {
                            item.RoleName = string.Join(ConstValue.ChineseSeparatorChar, list.Select(it => it.RoleName).ToArray());
                        }
                    }

                }
                #endregion
            }
            return result;
        }
        
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<ResultDto> Update(DoraUserEntity entity)
        {
            var oldEntity =await _repository.FirstOrDefaultAsync(entity.Id);
            if (oldEntity == null)
            {
                return ResultDto.Error("用户不存在");
            }

            if (!VerifyHelper.IsMobilePhone(entity.Mobile))
            {
                return ResultDto.Error("请输入正确的手机号");
            }

            if (string.IsNullOrWhiteSpace(entity.RealName))
            {
                return ResultDto.Error("请输入真实姓名");
            }

            if (!string.IsNullOrEmpty(entity.UserName))
            {
                var existUserName = await _repository.ExistUserName(entity.UserName, entity.Id);
                if (existUserName)
                {
                    return ResultDto.Error("用户名已经存在");
                }
            }

            if (!string.IsNullOrEmpty(entity.Mobile))
            {
                entity.MobileIsVerified = 1;
                if (entity.Mobile != oldEntity.Mobile)
                {
                    var existMobile = await _repository.ExistVerifiedMobile(entity.Mobile, entity.Id);
                    if (existMobile)
                    {
                        return ResultDto.Error("手机号已经存在");
                    }
                }
            }

            oldEntity.UserName = entity.UserName;
            oldEntity.Mobile = entity.Mobile;
            oldEntity.MobileIsVerified = entity.MobileIsVerified;
            oldEntity.Email = entity.Email;
            oldEntity.RealName = entity.RealName;
            oldEntity.Sex = entity.Sex;
            oldEntity.IDCardNO = entity.IDCardNO;
            oldEntity.Sort = entity.Sort;
            oldEntity.Avatar = entity.Avatar;
            oldEntity.Remark = entity.Remark;
            oldEntity.UpdatedUserId = entity.UpdatedUserId;
            oldEntity.UpdatedUserName = entity.UpdatedUserName;
            oldEntity.UpdatedTime = DateTime.Now;
            
            var result= await _repository.UpdateAsync(oldEntity);
            if (result)
            {
                return ResultDto.Success("修改成功");
            }
            else
            {
                return ResultDto.Error("修改失败");
            }
        }

        /// <summary>
        /// 根据IdList获取列表
        /// </summary>
        /// <param name="idList"></param>
        /// <returns></returns>
        public async Task<List<DoraUserEntity>> GetList(List<Guid> idList)
        {
            if (idList == null || idList.Count == 0)
            {
                return new List<DoraUserEntity>();
            }
            var list = await _repository.GetAllListAsync(it => idList.Contains(it.Id) && it.IsDeleted == 0);
            return list;
        }

        /// <summary>
        /// 获取所有
        /// </summary>
        /// <returns></returns>
        public async Task<List<DoraUserEntity>> GetAll()
        {
            var list = await _repository.GetAllListAsync(it => it.IsDeleted == 0);
            return list;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<bool> Delete(Guid id)
        {
            return await _repository.Delete(id) ;
        }
        public async Task<ResultDto<IdentityUserDto>> Login(string userName, string pwd, string ip, string systemKey)
        {
            var entity = new DoraUserEntity();
            if (VerifyHelper.IsMobilePhone(userName))
            {
                entity = await _repository.GetByVerifiedMobile(userName);
            }
            else if (VerifyHelper.IsEmail(userName))
            {
                entity = await _repository.GetByVerifiedEmail(userName);
            }
            else
            {
                entity= await _repository.GetByUserName(userName);
            }
            

            if (entity == null)
            {
                return ResultDto<IdentityUserDto>.Error("用户名密码错误");
            }
            if (string.IsNullOrWhiteSpace(entity.Password) || string.IsNullOrWhiteSpace(entity.Password))
            {
                return  ResultDto<IdentityUserDto>.Error("用户名或密码不能为空");
            }

            var encryPwd = DEncryptHelper.MD5Salt(pwd, entity.PasswordSalt);
            if (entity.Password != encryPwd)
            {
                return ResultDto<IdentityUserDto>.Error("用户名密码错误");
            }
            return await JudegLogin(entity, ip, UserLoginType.UserNameAndPwd, systemKey);
        }

        private async Task<ResultDto<IdentityUserDto>> JudegLogin(DoraUserEntity entity, string ip, UserLoginType loginType, string systemKey)
        {
            if (entity == null)
            {
                return ResultDto<IdentityUserDto>.Error("用户名密码错误");
            }
            if (entity.IsDisabled == 1)
            {
                return ResultDto<IdentityUserDto>.Error("用户被禁用");
            }
            else if (entity.IsDeleted == 1)
            {
                return ResultDto<IdentityUserDto>.Error("用户名密码错误");
            }
            else
            {
                var authKeyList = new List<AuthKeyItem>();

                var permissions = new List<PermissionEntity>();
                if (entity.IsSuperAdmin == 1)
                {
                    permissions = await _permissionRepository.GetAllListAsync(it => it.SystemKey == systemKey && it.IsDeleted == 0);
                }
                else
                {
                    permissions = await _permissionRepository.GetDoraAuthedListByUserId(entity.Id);
                }
                if (permissions?.Count > 0)
                {
                    foreach (var item in permissions)
                    {
                        authKeyList.Add(new AuthKeyItem() { AuthKey = item.AuthKey, Name = item.Name, Icon = item.Icon, Sort = item.Sort });
                    }
                    //authKeyList = permissions.Select(p => p.AuthKey).ToList();
                }

                _ = WriteLoginLog(systemKey, 0, entity.Id, entity.UserName, entity.RealName, ip, loginType);
                entity.Password = "";//不给前台返回
                entity.PasswordSalt = "";//不给前台返回

                var userDto = new IdentityUserDto
                {
                    Id = entity.Id,
                    SystemKey = DoraSysIdentifier.DAS.ToDescription(),
                    Avatar = entity.Avatar,
                    IsSuperAdmin = entity.IsSuperAdmin,
                    Mobile = entity.Mobile,
                    MobileIsVerified = entity.MobileIsVerified == 1 ? true : false,
                    RealName = entity.RealName,
                    UserName = entity.UserName,
                    AuthKeyList = authKeyList
                };

                return ResultDto<IdentityUserDto>.Success("登录成功", userDto);
            }
        }

        public async Task<DoraUserEntity> GetByUserName(string userName)
        {
            return await _repository.GetByUserName(userName);
        }

        public async Task<DoraUserEntity> GetByMobile(string mobile)
        {
            return await _repository.GetByMobile(mobile);
        }

        public async Task<ResultDto> UpdatePassword(Guid userId, string oldPassword, string newPassword)
        {
            var oldEntity = await GetById(userId);
            if (oldEntity == null)
            {
                return ResultDto.Error( "用户不存在",false);
            }
            if (string.IsNullOrWhiteSpace(newPassword))
            {
                return ResultDto.Error("密码不能为空", false);
            }

            var saltOldPassword = DEncryptHelper.MD5Salt(oldPassword, oldEntity.PasswordSalt);
            var saltNewPassword = DEncryptHelper.MD5Salt(newPassword, oldEntity.PasswordSalt);
            var mobilePassward = DEncryptHelper.GetInitPassword(oldEntity.Mobile, oldEntity.PasswordSalt);
            //if (saltNewPassword == mobilePassward)
            //{
            //    return ResultDto.Error("请不要使用默认密码作为新密码", false);
            //}
            if (saltNewPassword == saltOldPassword)
            {
                return ResultDto.Error("请使用和原密码不一样的新密码", false);
            }
            if (saltOldPassword != oldEntity.Password)
            {
                return ResultDto.Error("原密码错误", false);
            }

            oldEntity.Password = saltNewPassword;

            var result = await _repository.UpdatePassword(oldEntity);
            if (result)
            {
                return ResultDto.Success("修改成功", result);
            }
            else
            {
                return ResultDto.Error("修改失败", result);
            }
        }

        public async Task<List<DoraUserListDto>> GetListWithRoles(List<Guid> idList)
        {
            try
            {
                var userEntityList = await GetList(idList);
                var userList = new List<DoraUserListDto>();
                if (userEntityList?.Count > 0)
                {
                    var roleListAll = await _doraUserRoleMapRepository.GetListByUserIdList(idList);
                    if (roleListAll?.Count > 0)
                    {
                        foreach (var item in userEntityList)
                        {
                            var ermList = roleListAll.Where(p => p.UserId == item.Id).ToList();
                            DoraUserListDto dtoItem = new DoraUserListDto()
                            {
                                Id = item.Id,
                                UserName = item.UserName,
                                Mobile = item.Mobile,
                                MobileIsVerified = item.MobileIsVerified,
                                Email = item.Email,
                                EmailIsVerified = item.EmailIsVerified,
                                RealName = item.RealName,
                                Sex = item.Sex,
                                Sort = item.Sort,
                                IsDisabled = item.IsDisabled,
                                IsFrozen = item.IsFrozen,
                                IsSuperAdmin = item.IsSuperAdmin,
                                Avatar = item.Avatar,
                                Remark = item.Remark,
                                UserRoleMapList = ermList

                            };
                            if (dtoItem.UserRoleMapList == null)
                            {
                                dtoItem.UserRoleMapList = new List<DoraUserRoleMapListDto>();
                            }

                            userList.Add(dtoItem);
                        }
                    }
                }
                return userList;
            }
            catch (Exception ex)
            {
                //WriteOperationLog(EmployeeOperationType.Error, JsonConvert.SerializeObject(list), 0, "系统", ex.Message);
                return new List<DoraUserListDto>();
            }
        }

        public async Task<int> BindDoraUserRole(List<DoraUserRoleSaveDto> list)
        {
            if (list == null || list.Count == 0)
            {
                return 0;
            }
            var newList = new List<DoraUserRoleMapEntity>();
            if (list?.Count > 0)
            {
                foreach (var item in list)
                {
                    //var existCount = newList.Where(p => p.RoleId == item.RoleId && p.EmployeeId == item.EmployeeId).Count();
                    //if (existCount == 0)
                    //{
                    //    newList.Add(item);
                    //}
                    if (item.RoleIdList?.Count > 0)
                    {
                        var roleIdIdHash = item.RoleIdList.ToHashSet();
                        foreach (var roleId in roleIdIdHash)
                        {
                            newList.Add(new DoraUserRoleMapEntity() { UserId = item.UserId, RoleId = roleId });
                        }
                    }
                }
            }
            else
            {
                return 0;
            }
            var userIdList = list.Select(p => p.UserId).Distinct().ToList();
            await _doraUserRoleMapRepository.DeleteByUserIdList(userIdList);

            var num = 0;
            if (newList.Count > 0)
            {
                num = await _doraUserRoleMapRepository.CreateRange(newList);
            }
            else
            {
                num = 1;
            }

            #region 更新员工的缓存权限
            try
            {

                if (userIdList?.Count > 0)
                {
                    foreach (var eId in userIdList)
                    {
                        RefreshRedisToken(eId);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"SaveRolePermission error:{ex.Message} {ex.StackTrace}");
            }
            #endregion
            return num;
        }

        public async Task<ResultDto> ResetPassword(Guid userId, string password)
        {
            var entity = await GetById(userId);
            if (entity == null)
            {
                return ResultDto.Error("用户不存在", false);
            }
            if (string.IsNullOrWhiteSpace(password))
            {
                return ResultDto.Error("密码不能为空", false);
            }

            var saltOldPassword = entity.Password;
            var saltNewPassword = DEncryptHelper.MD5Salt(password, entity.PasswordSalt);
            var mobilePassward = DEncryptHelper.GetInitPassword(entity.Mobile, entity.PasswordSalt);
            //if (saltNewPassword == mobilePassward)
            //{
            //    return ResultDto.Error("请不要使用默认密码作为新密码", false);
            //}
            if (saltNewPassword == saltOldPassword)
            {
                return ResultDto.Error("请使用和原密码不一样的新密码", false);
            }

            entity.Password = DEncryptHelper.MD5Salt(password, entity.PasswordSalt);

            var result = await _repository.UpdatePassword(entity);
            if (result)
            {
                return ResultDto.Success("重置成功", result);
            }
            else
            {
                return ResultDto.Error("重置失败", result);
            }
        }
        /// <summary>
        /// 刷新用户redis
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<bool> RefreshRedisToken(Guid userId)
        {
            try
            {

                var user = await GetById(userId);
                if (user == null)
                {
                    return false;
                }

                var permissions = new List<PermissionEntity>();
                if (user.IsSuperAdmin == 1)
                {
                    permissions = await _permissionRepository.GetAllListAsync();
                }
                else
                {
                    permissions = await _permissionRepository.GetDoraAuthedListByUserId(user.Id);
                }


                //var authKeyList = permissionEntities.Select(p => p.AuthKey).ToList();
                var authKeyList = new List<AuthKeyItem>();
                if (permissions?.Count > 0)
                {
                    //authKeyList = permissions.Select(p => p.AuthKey).ToList();

                    foreach (var item in permissions)
                    {
                        authKeyList.Add(new AuthKeyItem() { AuthKey = item.AuthKey, Name = item.Name, Icon = item.Icon, Sort = item.Sort });
                    }
                }

                return await TokenHelper.SetAuthKeyAsync(user.Id.ToString(), authKeyList);
            }
            catch (Exception ex)
            {
                _ = WriteOperationLog(OperationType.Error, new { userId, ex.Message, ex.StackTrace }, Guid.Empty, "系统", "DoraUserService RefreshRedisToken");
                Console.WriteLine($"DoraUserService RefreshRedisToken error:{ex.Message} {ex.StackTrace}");
                return false;
            }
        }

        public async Task<List<Guid>> GetIdListByRoleIdList(List<Guid> roleIdList)
        {
            var systemList = await _doraUserRoleMapRepository.GetListByRoleIdList(roleIdList);
            return systemList.Select(p => p.UserId).ToList();
        }

        public async Task<ResultDto> ResetPassword4Forget(string mobile, string code, string password)
        {
            var entity = await _repository.GetByVerifiedMobile(mobile);
            if (entity == null)
            {
                return new ResultDto(ResultCode.Fail, "用户不存在", null);
            }
            if (string.IsNullOrWhiteSpace(password))
            {
                return new ResultDto(ResultCode.Fail, "密码不能为空", null);
            }
            if (GenerateVerifyCode.GetVerifyCode(mobile) != code)
            {
                return new ResultDto(ResultCode.Fail, "验证码错误", null);
            }

            var saltOldPassword = entity.Password;
            var saltNewPassword = DEncryptHelper.MD5Salt(password, entity.PasswordSalt);
            var mobilePassward = DEncryptHelper.GetInitPassword(entity.Mobile, entity.PasswordSalt);
            //if (saltNewPassword == mobilePass ward)
            //{
            //    return new ResultDto(ResultCode.Fail, "请不要使用默认密码作为新密码", null);
            //}
            if (saltNewPassword == saltOldPassword)
            {
                return new ResultDto(ResultCode.Fail, "请使用和原密码不一样的新密码", null);
            }

            entity.Password = saltNewPassword;

            var isSuccess = await _repository.UpdatePassword(entity);
            if (isSuccess)
            {
                GenerateVerifyCode.RemoveVerifyCode(mobile);
                return new ResultDto(ResultCode.Success, "修改成功，请重新登录", null);
            }
            return new ResultDto(ResultCode.Fail, "修改失败,请重试", null);
        }

        /// <summary>
        /// 用户禁用
        /// </summary>
        /// <param name="id"></param>
        /// <param name="opId"></param>
        /// <param name="opName"></param>
        /// <returns></returns>
        public async Task<bool> Disable(Guid id,Guid opId,string opName)
        {
            var entity = await _repository.FirstOrDefaultAsync(id);
            if (entity == null)
            {
                return false;
            }

            entity.IsDisabled = 1;
            entity.UpdatedTime = DateTime.Now;
            entity.UpdatedUserId = opId;
            entity.UpdatedUserName = opName;

            var result = await _repository.IsDisabled(entity);
            return result;
        }

        /// <summary>
        /// 用户启用
        /// </summary>
        /// <param name="id"></param>
        /// <param name="opId"></param>
        /// <param name="opName"></param>
        /// <returns></returns>
        public async Task<bool> Enable(Guid id, Guid opId, string opName)
        {
            var entity = await _repository.FirstOrDefaultAsync(id);
            if (entity == null)
            {
                return false;
            }

            entity.IsDisabled = 0;
            entity.UpdatedTime = DateTime.Now;
            entity.UpdatedUserId = opId;
            entity.UpdatedUserName = opName;

            var result = await _repository.IsDisabled(entity);
            return result;
        }

        /// <summary>
        /// 用户冻结
        /// </summary>
        /// <param name="id"></param>
        /// <param name="opId"></param>
        /// <param name="opName"></param>
        /// <returns></returns>
        public async Task<bool> Frozen(Guid id, Guid opId, string opName)
        {
            var entity = await _repository.FirstOrDefaultAsync(id);
            if (entity == null)
            {
                return false;
            }

            entity.IsFrozen = 1;
            entity.UpdatedTime = DateTime.Now;
            entity.UpdatedUserId = opId;
            entity.UpdatedUserName = opName;

            var result = await _repository.IsFrozen(entity);
            return result;
        }

        /// <summary>
        /// 用户解冻
        /// </summary>
        /// <param name="id"></param>
        /// <param name="opId"></param>
        /// <param name="opName"></param>
        /// <returns></returns>
        public async Task<bool> UnFrozen(Guid id, Guid opId, string opName)
        {
            var entity = await _repository.FirstOrDefaultAsync(id);
            if (entity == null)
            {
                return false;
            }

            entity.IsFrozen = 0;
            entity.UpdatedTime = DateTime.Now;
            entity.UpdatedUserId = opId;
            entity.UpdatedUserName = opName;

            var result = await _repository.IsFrozen(entity);
            return result;
        }
    }
}
